<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        function fn()
        {
            /* 
                arguments
                    - arguments是函数中有一个隐含参数
                    - arguments是一个类数组对象（伪数组）
                        和数组相似，可以通过索引来读取元素，也可以通过for循环变量，但是它不是一个数组对象，不能调用数组的方法
                    - arguments用来存储函数的实参
                        无论用户是否定义形参，实参都会存储到 arguments 对象中
                        可以通过该对象直接访问实参
            */
           console.log(arguments[1])
        }
        fn(1,2,3)

        /* 
            可变参数，在定义函数时可以将参数指定为可变参数
                - 可变参数可以接受任意数量实参，并将他们统一存储倒一个数组中返回
                - 可变参数的作用和 arguments 一样，都可以通过 arguments 对象访问，但也具有不同点：
                    1. 可变参数的名字可以自己指定
                    2. 可变参数就是一个数组，可以直接使用数组的方法
                    3. 可变参数可以配合其他参数一起使用
        */
        function sum(...nums){
            let sum = 0;
            for(let i = 0; i < nums.length; i++){
                sum += nums[i];
            }
            return sum;
        }
        console.log(sum(1,2,3,4,5));

        // 配合其他参数一起使用时，要把可变参数放在最后
        function sum2(a,b,...nums){
            let sum = a + b;
            for(let i = 0; i < nums.length; i++){
                sum += nums[i];
            }
            return sum;
        }

        /* 
            根据函数调用方式的不同，this的值也不同：
                1. 以函数形式调用，this是window
                2. 以对象方法调用，this是调用对象
                3. 构造函数调用，this是实例对象
                4. 箭头函数调用，this是外层作用域的this
                5. 通过call和apply调用，this是调用者指定
                6. 通过bind调用，this是bind时指定的对象（无法修改）

            bind() 是函数的方法，可以用来创建一个新的函数
                - bind可以为新函数绑定this
                - bind可以为新函数绑定参数

            箭头函数没有自身的this，它的this是外层作用域的this
                箭头函数的this不能被call、apply、bind修改
                箭头函数也没有arguments
        */

        /* 
            JavaScript 的 this 是调用时决定的，不像 C++ 那样固定。
            如果你要在别的对象上调用某个函数，就需要 call、apply、bind 来改变 this
        */
        function sayHello(greeting) {
            console.log(`${greeting}, 我是 ${this.name}`);
        }

        const person = { name: "小明" };
        sayHello.call(person, "hello");  // 立刻调用函数，并将 this 设置为传入的对象。
        sayHello.apply(person, ["hello"]);  // 和 call 一样，只是参数传法不同：用数组。
        const bindSayHello = sayHello.bind(person, "hello");
        bindSayHello();  // 不会立刻调用，而是返回一个新的函数，里面的 this 永远是你绑定的那个对象。

    </script>
</head>
<body>
    
</body>
</html>